/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "ui曲线编辑器.h"
#include "A_引擎/文件工程/工程文件.h"


static bool g移动视口 = false;
static bool g纵向缩放 = false;
static bool g移动控制点 = false;

static uint32	g网格线绘制属性 = 0;
static uint32	g曲线绘制属性 = 0;
static vec2		g节点鼠标局部位置 = { 0,0 };


static vec2 g选框起点坐标;
static vec2 g选框终点坐标;

C_曲线编辑视口*				C_曲线编辑视口::g当前操作曲线视口 = nullptr;
std::set<C_曲线编辑视口*>	C_曲线编辑视口::g_曲线视口页面;




static void on_曲线视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	f_Widget_计算视口缩放保持偏移比例(self);
}

void on_曲线视口绘制(C_Widget* self, S_2D画布* 画布) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	box->m_背景绘制.m_属性 = f_vg_gen属性(画布);

	S_凸边图元 图元 = {};
	图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	box->m_背景绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色填充);
	

	g网格线绘制属性 = f_vg_gen属性(画布);
	box->m_刻度线绘制.f_Draw网格(画布, g网格线绘制属性);

	图元 = {};
	图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	box->m_选框线绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色描边);

	

	g曲线绘制属性 = f_vg_gen属性(画布);
	box->m_曲线绘制.f_Draw(画布, g曲线绘制属性, true);
	box->m_曲线绘制.f_Draw控制点(画布, g曲线绘制属性);

	
	const auto& 字体 = f_surface_get字体库(*self->m_UIctx, S_UI主题::ui_默认字体);
	box->m_标签绘制.m_画布属性 = f_vg_gen属性(画布);
	box->m_标签绘制.f_Draw(画布, &字体, box->m_标签绘制.m_画布属性);


	//时间线绘制
	图元 = {};
	图元.属性 = f_vg_get属性指针(画布, box->m_背景绘制.m_属性);
	box->m_时间线绘制.f_Draw(画布, 图元, E_笔刷类型::e_单色描边);


	S_2D顶点属性 属性 = { {1,1}, {1,1}, 1, 3 };
	f_vg_set属性(画布, box->m_背景绘制.m_属性, 属性);

	box->m_是否未绘制 = false;
}

void on_曲线视口变换修改(C_Widget* self) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;


	S_2D顶点属性 属性 = { {1,1}, {0,0}, 1, 3 };
	属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	f_vg_set属性(self->m_画布, box->m_背景绘制.m_属性, 属性);
	

	属性 = { {1,1}, {0,0}, 1, 3 };
	属性.m_比例 = self->m_扩展视口属性->m_比例;
	属性.m_偏移 = self->m_扩展视口属性->m_中心;
	属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	属性.m_间隔 = 3;
	f_vg_set属性(self->m_画布, g网格线绘制属性, 属性);


	属性 = { {1,1}, {0,0}, 1, 3 };
	属性.m_偏移 = {self->m_扩展视口属性->m_中心.x, 0};
	f_vg_set属性(self->m_画布, box->m_标签绘制.m_画布属性, 属性);


	mat3X2 mat;
	mat.row0 = {};
	mat.row1 = self->m_Size;
	mat.row2 = {1,0};

	box->m_背景绘制.f_alloc(3);
	box->m_背景绘制.f_set单色填充(0, mat, S_主题颜色::uic_时间轴背景, S_Widget预设图元::m_矩形);
	mat = f_时间工作区_时间区间绘制矩阵(self);

	
	mat.row1.y = self->m_Size.y;
	box->m_背景绘制.f_set单色填充(1, mat, S_主题颜色::uic_时间轴时间区, S_Widget预设图元::m_矩形);

	//box->m_选框线绘制.f_alloc(1);
	//box->m_选框线绘制.f_set单色填充(0, mat, {50, 50, 200, 255}, S_Widget预设图元::m_矩形);

	

	vec2 帧绘制间隔宽度 = mat.row1;
	vec2 刻度线步进宽度 = f_时间工作区_计算尺线绘制间隔(帧绘制间隔宽度);

	box->m_刻度线绘制.f_alloc(1);
	mat.row0 = {};
	mat.row1 = self->m_Size;
	mat.row2 = 刻度线步进宽度 * 2;
	box->m_刻度线绘制.f_set(2048, mat, S_主题颜色::uic_时间网格线);
	



	属性 = { {1,1}, {0,0}, 1, 3 };
	属性.m_比例 = self->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放;
	属性.m_偏移 = self->m_扩展视口属性->m_中心;
	属性.m_渐变数量 = box->m_GPU内存分配维度大小.x;
	f_vg_set属性(self->m_画布, g曲线绘制属性, 属性);
	

	box->m_是否未绘制 = false;
	box->f_重建曲线绘制();
	
	
	vec2 数量步进 = f_时间工作区_计算刻度文本_数量步进(帧绘制间隔宽度.x, 刻度线步进宽度.x);
	box->m_标签绘制.f_alloc(数量步进.x, 12);
	box->m_标签绘制.f_绘制刻度数字(S_Rect2Df{ {0.0f,0.0f}, {60.0f,10.0f} }, int32(数量步进.x), { 0, 数量步进.y }, 刻度线步进宽度.x * 2);
	
	//f_时间工作区_刷新时间线绘制(box, box->m_时间线绘制, f_prop_I32(f_NodeCtx_get帧().当前帧), self->m_父部件->m_Size.y);
	f_时间工作区_时间线绘制(box, box->m_时间线绘制);
}

bool on_曲线视口按键(C_Widget* self, const S_键盘& ks) {
	if (f_KS(ks, S_InputKey::e_KEY_左CTRL) == DEF_按键状态_按下中) {
		g纵向缩放 = true;
	}
	else {
		g纵向缩放 = false;
	}
	return false;
}

bool on_曲线视口鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = true;
	}
	return false;
}

bool on_曲线视口鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g移动视口 = false;
	}
	return false;
}

bool on_曲线视口缩放(C_Widget* self, const S_鼠标& 鼠标) {
	vec2 s = {1,1};
	if (鼠标.lZ > 0) {
		if (g纵向缩放) {
			s.y = 1.15;
		}
		else {
			s.x = 1.15;
			s.y = 1.15;
		}
	}
	else if (鼠标.lZ < 0) {
		if (g纵向缩放) {
			s.y = 0.9;
		}
		else {
			s.x = 0.9;
			s.y = 0.9;
		}
	}
	f_C_Widget_鼠标位置视口缩放(self, s);
	return false;
}

bool on_曲线视口移动(C_Widget* self, const ivec4& value) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;
	C_曲线编辑视口::g当前操作曲线视口 = box;

	if (g移动视口) {
		self->m_扩展视口属性->m_中心.x += C_Widget::g_鼠标.abs.x;
		self->m_扩展视口属性->m_中心.y += C_Widget::g_鼠标.abs.y;
		self->m_绘制属性更新 = true;
	}
	else {
		
	}

	if (g移动控制点) {
		vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);


		uint32 num = box->m_拾取索引.size();
		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto offset_coord = box->m_先对偏移[i];

			auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
			switch (point.Select_Type.y) {
			case DEF_CONTORL_POINT_AUTO:
				point.value = 拾取坐标 + offset_coord;
				break;
			case DEF_CONTORL_POINT_FREE:
				
				if (point.Select_Type.x & 1 << 0) {
					
					point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
					point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;

					point.value = 拾取坐标 + offset_coord;
				}
				if (point.Select_Type.x & 1 << 1) {
					point.L_point = 拾取坐标;
				}
				if (point.Select_Type.x & 1 << 2) {
					point.R_point = 拾取坐标;
				}
				break;
			case DEF_CONTORL_POINT_ALGNED:
				point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
				point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;
				break;
			case DEF_CONTORL_POINT_VECTOR:
				point.value = 拾取坐标 + offset_coord;
				point.L_point = (point.L_point - point.value) + offset_coord + 拾取坐标;
				point.R_point = (point.R_point - point.value) + offset_coord + 拾取坐标;
				break;
			}
			
			
		}

		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto& 曲线 = box->m_动画曲线[index.组]->曲线[index.通道];
			f_an_曲线值排序(曲线);
			f_an_自动控制点(曲线);
		}

		
		/*box->m_曲线绘制.f_map();
		for (uint32 i = 0; i < num; ++i) {
			auto index = box->m_拾取索引[i];
			auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
			box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
		}
		box->m_曲线绘制.f_unmap();*/

		box->f_重建曲线绘制();
	}

	return false;
}



static E_事件是否传递 on_曲线编辑视口准备拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	
	//g选框起点坐标 = (mousePos - box->m_扩展视口属性->m_中心) / box->m_扩展视口属性->m_比例;


	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 on_曲线编辑视口拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	


	return E_事件是否传递::e_事件传递_终止;
}

static bool on_曲线编辑视口结束拖放(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {
	
	f_工作区_完成移动控制点(self, 0);
	return true;
}

static bool on_曲线编辑视口打开关闭(C_Widget* self, bool show) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;
	C_曲线编辑视口::g当前操作曲线视口 = box;

	box->f_重建曲线绘制();

	return true;
}

C_曲线编辑视口::C_曲线编辑视口(S_UI创建环境& ctx) : C_Widget(&ctx) {
	mf_布局Fun = on_曲线视口布局;
	mf_DrawFun = on_曲线视口绘制;
	mf_变换修改 = on_曲线视口变换修改;

	mf_鼠标移动 = on_曲线视口移动;
	mf_鼠标按键按下 = on_曲线视口鼠标按下;
	mf_鼠标按键放开 = on_曲线视口鼠标放开;
	mf_键盘按键敲击 = on_曲线视口按键;
	//mf_鼠标按键点击 = on_曲线视口控制点选择;

	mf_开始拖拽 = on_曲线编辑视口准备拖动;
	mf_拖拽 = on_曲线编辑视口拖动;
	mf_结束拖拽 = on_曲线编辑视口结束拖放;

	//mf_打开关闭 = on_曲线编辑视口打开关闭;

	m_是否未绘制 = true;
	g当前操作曲线视口 = this;

	C_曲线编辑视口::g_曲线视口页面.insert(this);
}

C_曲线编辑视口::~C_曲线编辑视口() {
	C_曲线编辑视口::g_曲线视口页面.erase(this);
}

void C_曲线编辑视口::f_旋转辅助线绘制(vec2 中心坐标, float32 角度弧度, float32 长度) {

}

void C_曲线编辑视口::f_缩放辅助线绘制(vec2 中心坐标, float32 角度弧度, float32 长度) {

}

void C_曲线编辑视口::f_重建曲线绘制() {
	
	if (m_是否未绘制) {
		return;
	}

	m_拾取索引.clear();

	//auto curvs = m_动画曲线.data();
	//uint32 num = m_动画曲线.size();
	uint32 曲线组数量 = m_动画曲线.size();
	auto* curvs = m_动画曲线.data();

	uint32 所有点数量 = 0;
	for (uint32 i = 0; i < 曲线组数量; ++i) {
		auto 通道 = curvs[i];
		//迭代通道
		for (uint32 t = 0; t < 通道->count; ++t) {
			所有点数量 += 通道->曲线[t]->count;
		}
	}
	

	m_曲线绘制.f_begin(所有点数量);

	uint32 offset = 0;
	for (uint32 i = 0; i < 曲线组数量; ++i) {
		auto 通道 = curvs[i];

		//迭代通道
		for (uint32 t = 0; t < 通道->count; ++t) {
				
			uint32 num = 通道->曲线[t]->count;
			S_CurvePoint* point = 通道->曲线[t]->point;

			for (uint32 k = 0; k < num; ++k) {
				if (k == num - 1) {
					point[k].ID_Color.x = 0xffffffff;
				}
				else {
					point[k].ID_Color.x = offset + 1;
				}
				m_曲线绘制.f_setPoint(offset, point[k]);
				m_曲线绘制.f_setPointSelect(offset, point[k].Select_Type.x);

				if (point[k].Select_Type.x) {
					S_曲线扩展点拾取ID 索引 = {};

					索引.组 = i;
					索引.通道 = t;
					索引.点ID = k;
					索引.GPU偏移 = offset;
					索引.控制点 = point[k].Select_Type.x;

					m_拾取索引.push_back(索引);
				}
				
				++offset;
			}
		}
	}

	m_曲线绘制.f_end();

}





C_Widget* f_工作区页面_创建曲线视口(S_UI创建环境& ctx) {
	C_曲线编辑视口* ui曲线编辑视口 = new C_曲线编辑视口(ctx);

	f_widget_开启视口属性(ui曲线编辑视口);
	ui曲线编辑视口->m_扩展视口属性->m_大小 = { 1024, 1024 };

	auto* 滚动窗口 = f_ui_创建滚动框(ctx, true, true, ui曲线编辑视口);
	滚动窗口->mf_鼠标滚轮 = nullptr;


	S_鼠标键位映射* 鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_横向缩放页面视口;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->键盘按键[0] = S_InputKey::e_KEY_左SHIFT;
	鼠标键位->键盘状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_纵向缩放页面视口;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->键盘按键[0] = S_InputKey::e_KEY_左CTRL;
	鼠标键位->键盘状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_缩放页面视口;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_滚轮;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_曲线页面工作区_拖拽时间帧;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	S_拖拽键位映射* 拖拽键位 = f_widget_init_拖拽键位映射();
	拖拽键位->event = f_曲线页面工作区_拖拽时间帧;
	拖拽键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	拖拽键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖拽键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)拖拽键位);



	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_准备框选控制点;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_框选控制点;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_放开;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	拖拽键位 = f_widget_init_拖拽键位映射();
	拖拽键位->event = f_工作区_拖拽曲线视口选框;
	拖拽键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	拖拽键位->鼠标状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	拖拽键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)拖拽键位);

	


	S_键盘键位映射* 快捷键 = f_widget_init_键盘位映射();
	快捷键->event = f_工作区_开启移动控制点;
	快捷键->键盘按键[0] = S_InputKey::e_KEY_G;
	快捷键->键盘状态[0] = DEF_按键状态_按下;
	快捷键->发生组件 = ui曲线编辑视口;
	f_ui_注册键盘快捷键(滚动窗口, 快捷键);

	鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_完成移动控制点;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_左键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_放开;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);

	/*鼠标键位 = f_widget_init_鼠标键位映射();
	鼠标键位->event = f_工作区_取消移动控制点;
	鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	鼠标键位->鼠标状态[0] = DEF_按键状态_按下中 | DEF_按键状态_放开;
	鼠标键位->发生组件 = ui曲线编辑视口;
	f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);*/

	//鼠标键位 = f_widget_init_鼠标键位映射();
	//鼠标键位->event = f_工作区_点选控制点;
	//鼠标键位->鼠标按键[0] = E_Input_鼠标按键::e_右键;
	//鼠标键位->鼠标状态[0] = DEF_按键状态_按下;
	//鼠标键位->发生组件 = ui曲线编辑视口;
	//f_ui_注册鼠标快捷键(滚动窗口, (S_键位映射*)鼠标键位);
	
	//快捷键 = f_widget_init_键盘位映射();
	//快捷键->event = f_工作区_开启移动控制点;
	//快捷键->键盘按键[0] = S_InputKey::e_KEY_G;
	//快捷键->键盘状态[0] = DEF_按键状态_按下 | DEF_按键状态_按下中;
	//f_ui_注册键盘快捷键(滚动窗口, 快捷键);

	return 滚动窗口;
}

void f_工作区页面_设置当前编辑节点() {
	
	
}







E_事件是否传递 f_曲线页面工作区_拖拽时间帧(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	if (!g移动控制点) {
		f_时间工作区_从鼠标位置计算时间帧(self);

		//f_时间工作区_时间线绘制(box, box->m_时间线绘制);
		for (auto& e : C_曲线编辑视口::g_曲线视口页面) {
			f_时间工作区_刷新时间线绘制(e, e->m_时间线绘制, f_prop_I32(f_NodeCtx_get帧().当前帧), self->m_父部件->m_Size.y);
		}

		f_node_帧更新(true);
		//f_node_Step节点数(1);
		//f_node_帧更新(false);
		f_页面_更新联动工作区(E_工作区类型::e_曲线视口);
	}

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_准备框选控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;
	
	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	g选框起点坐标 = (mousePos);
	g选框终点坐标 = g选框起点坐标;
	return E_事件是否传递();
}

E_事件是否传递 f_工作区_拖拽曲线视口选框(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	g选框终点坐标 = (mousePos);
	
	box->m_背景绘制.f_alloc(3);
	box->m_选框线绘制.f_alloc(1);

	mat3X2 mat;
	mat.row0 = g选框起点坐标;
	mat.row1 = g选框终点坐标 - mat.row0;
	mat.row2 = { 1,0 };

	box->m_背景绘制.f_set单色填充(2, mat, S_RGBA8UI{ 60,80,160,100 }, S_Widget预设图元::m_圆角矩形);
	
	S_LineProp lp = {0, f_PackData4X8(S_RGBA8UI{ 100,100,255,200 }), f_PackData4X8(S_RGBA8UI{ 100,100,255,200 }) };
	box->m_选框线绘制.f_set单色线(0, mat, lp, S_Widget预设图元::m_圆角矩形);

	//g移动控制点 = false;
	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_框选控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;


	//取消移动
	if (g移动控制点) {
		uint32 num = box->m_暂存位置.size();

		if (num) {
			box->m_曲线绘制.f_map();

			for (uint32 i = 0; i < num; ++i) {
				auto index = box->m_拾取索引[i];
				auto coord = box->m_暂存位置[i];

				auto& 曲线 = box->m_动画曲线[index.组]->曲线[index.通道];
				auto& point = 曲线->point[index.点ID];
				point.value = coord.p1;
				point.L_point = coord.p2;
				point.R_point = coord.p3;

				f_an_曲线值排序(曲线);
				f_an_自动控制点(曲线);

				box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
			}
			box->m_曲线绘制.f_unmap();
		}

		g移动控制点 = false;
		return E_事件是否传递::e_事件传递_终止;
	}



	box->m_背景绘制.f_Close(2);
	box->m_选框线绘制.f_Close();



	vec2 选框起点坐标 = (g选框起点坐标 - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);
	vec2 选框终点坐标 = (g选框终点坐标 - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);

	vec2 选框起点 = vec_Min(选框起点坐标, 选框终点坐标);
	vec2 选框终点 = vec_Max(选框起点坐标, 选框终点坐标);

	vec2 选框大小 = 选框终点 - 选框起点;


	uint32 曲线组数量 = box->m_动画曲线.size();
	auto* curvs = box->m_动画曲线.data();

	if(选框大小.x < 2 || 选框大小.y < 2) {
		vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);

		if (曲线组数量) {
			box->m_曲线绘制.f_map();

			//清空拾取绘制焦点
			auto 上一次拾取控制点的索引 = box->m_拾取索引;
			

			box->m_拾取索引.clear();
			box->m_暂存位置.clear();
			box->m_先对偏移.clear();


			float32 最小距离 = 3;
			S_曲线扩展点拾取ID 索引 = {};

			uint32 offset = 0;
			vec2 coord = {};
			for (uint32 i = 0; i < 曲线组数量; ++i) {
				auto 通道 = curvs[i];

				//迭代通道
				for (uint32 t = 0; t < 通道->count; ++t) {
					uint32 num = 通道->曲线[t]->count;

					for (uint32 k = 0; k < num; ++k) {
						S_CurvePoint& point = 通道->曲线[t]->point[k];
						uint32 color = point.ID_Color.y;

						uint32 当前GPU内存偏移 = offset;
						++offset;
						std::cout<<"point.Select_Type.x = " << point.Select_Type.x << std::endl;
						float32 距离 = vec_len(point.value - 拾取坐标);
						if (距离 < 最小距离) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1;
						}

						距离 = vec_len(point.L_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x|7) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<1;
						}

						距离 = vec_len(point.R_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x&7) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<2;
						}
					}
				}
			}


			//清空拾取绘制焦点
			for (auto& 索引 : 上一次拾取控制点的索引) {
				box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
				curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
			}



			box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 索引.控制点);
			curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 索引.控制点;

			box->m_曲线绘制.f_unmap();


			auto& point = curvs[索引.组]->曲线[索引.通道]->point[索引.点ID];

			box->m_拾取索引.push_back(索引);
			box->m_暂存位置.push_back({point.value, point.L_point, point.R_point});
			box->m_先对偏移.push_back(coord - 拾取坐标);
		}

	}
	else {
		box->m_曲线绘制.f_map();
		for (auto& 索引 : box->m_拾取索引) {
			box->m_动画曲线[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
			box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
		}

		box->m_拾取索引.clear();
		box->m_暂存位置.clear();
		box->m_先对偏移.clear();



		uint32 offset = 0;
		for (uint32 i = 0; i < 曲线组数量; ++i) {
			auto 通道 = curvs[i];

			//迭代通道
			for (uint32 t = 0; t < 通道->count; ++t) {
				uint32 num = 通道->曲线[t]->count;

				for (uint32 k = 0; k < num; ++k) {
					S_CurvePoint& point = 通道->曲线[t]->point[k];
					uint32 color = point.ID_Color.y;

					uint32 当前GPU内存偏移 = offset;
					++offset;

					uint32 点选择遮罩 = 0;

					if (point.value.x < 选框起点.x || point.value.y < 选框起点.y) {
					}
					else if (point.value.x > 选框终点.x || point.value.y > 选框终点.y) {
					}
					else {
						点选择遮罩 |= 1<<0;
					}

					if (point.L_point.x < 选框起点.x || point.L_point.y < 选框起点.y) {
					}
					else if (point.L_point.x > 选框终点.x || point.L_point.y > 选框终点.y) {
					}
					else if(point.Select_Type.x&1) {
						点选择遮罩 |= 1<<1;
					}

					if (point.R_point.x < 选框起点.x || point.R_point.y < 选框起点.y) {
					}
					else if (point.R_point.x > 选框终点.x || point.R_point.y > 选框终点.y) {
					}
					else if(point.Select_Type.x&1) {
						点选择遮罩 |= 1<<2;
					}


					if (点选择遮罩) {
						point.Select_Type.x = 点选择遮罩;
						box->m_曲线绘制.f_setPointSelect(当前GPU内存偏移, 点选择遮罩);
						box->m_拾取索引.push_back({ i, t, k, 当前GPU内存偏移 });
					}
				}
			}
		}

		box->m_曲线绘制.f_unmap();
	}

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_点选控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	if (g移动控制点) {
		uint32 num = box->m_暂存位置.size();

		if (num) {
			box->m_曲线绘制.f_map();

			for (uint32 i = 0; i < num; ++i) {
				auto index = box->m_拾取索引[i];
				auto coord = box->m_暂存位置[i];

				auto& point = box->m_动画曲线[index.组]->曲线[index.通道]->point[index.点ID];
				point.value = coord.p1;
				point.L_point = coord.p2;
				point.R_point = coord.p3;

				box->m_曲线绘制.f_setPoint(index.GPU偏移, point);
			}
			box->m_曲线绘制.f_unmap();
		}


	}
	else {

		vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
		vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);



		uint32 曲线组数量 = box->m_动画曲线.size();
		if (曲线组数量) {
			auto* curvs = box->m_动画曲线.data();

			box->m_曲线绘制.f_map();

			//清空拾取绘制焦点
			for (auto& 索引 : box->m_拾取索引) {
				box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 0);
				curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 0;
			}

			box->m_拾取索引.clear();
			box->m_暂存位置.clear();
			box->m_先对偏移.clear();


			float32 最小距离 = 3;
			S_曲线扩展点拾取ID 索引 = {};

			uint32 offset = 0;
			vec2 coord = {};
			for (uint32 i = 0; i < 曲线组数量; ++i) {
				auto 通道 = curvs[i];

				//迭代通道
				for (uint32 t = 0; t < 通道->count; ++t) {
					uint32 num = 通道->曲线[t]->count;

					for (uint32 k = 0; k < num; ++k) {
						S_CurvePoint& point = 通道->曲线[t]->point[k];
						uint32 color = point.ID_Color.y;

						uint32 当前GPU内存偏移 = offset;
						++offset;

						float32 距离 = vec_len(point.value - 拾取坐标);
						if (距离 < 最小距离) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1;
						}

						距离 = vec_len(point.L_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x&1) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<1;
						}

						距离 = vec_len(point.R_point - 拾取坐标);
						if (距离 < 最小距离 && point.Select_Type.x&1) {
							最小距离 = 距离;

							索引.组 = i;
							索引.通道 = t;
							索引.点ID = k;
							索引.GPU偏移 = 当前GPU内存偏移;
							索引.控制点 = 1<<2;
						}
					}
				}
			}

			box->m_曲线绘制.f_setPointSelect(索引.GPU偏移, 索引.控制点);
			curvs[索引.组]->曲线[索引.通道]->point[索引.点ID].Select_Type.x = 索引.控制点;

			box->m_曲线绘制.f_unmap();

			auto& point = curvs[索引.组]->曲线[索引.通道]->point[索引.点ID];
			控制点坐标 暂存位置;
			暂存位置.p1 = point.value;
			暂存位置.p2 = point.L_point;
			暂存位置.p3 = point.R_point;

			box->m_拾取索引.push_back(索引);
			box->m_暂存位置.push_back(暂存位置);
			box->m_先对偏移.push_back(coord - 拾取坐标);
		}
	}
	
	g移动控制点 = false;

	return E_事件是否传递::e_事件传递_终止;
}


E_事件是否传递 f_工作区_开启移动控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	g移动控制点 = true;

	vec2 mousePos = f_widget_get鼠标局部位置(C_Widget::g_鼠标.gPos, self);
	vec2 拾取坐标 = (mousePos - box->m_扩展视口属性->m_中心) / (box->m_扩展视口属性->m_比例 * S_时间轴帧绘制信息::g时间区间缩放);


	box->m_先对偏移.clear();
	box->m_暂存位置.clear();
	for (auto& id : box->m_拾取索引) {
		auto& coord = box->m_动画曲线[id.组]->曲线[id.通道]->point[id.点ID];
		box->m_暂存位置.push_back({coord.value, coord.L_point, coord.R_point});
		box->m_先对偏移.push_back(coord.value - 拾取坐标);
	}

	return E_事件是否传递::e_事件传递_终止;
}

/*E_事件是否传递 f_工作区_移动控制点(C_Widget* self, uint8 状态) {
	if (g移动控制点) {
	}
	return E_事件是否传递::e_事件传递_终止;
}*/

E_事件是否传递 f_工作区_完成移动控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	g移动控制点 = false;

	//box->m_拾取索引.clear();
	//box->m_暂存位置.clear();
	//box->m_先对偏移.clear();

	return E_事件是否传递::e_事件传递_终止;
}

E_事件是否传递 f_工作区_取消移动控制点(C_Widget* self, uint8 状态) {
	C_曲线编辑视口* box = (C_曲线编辑视口*)self;

	if (g移动控制点) {
		
	}
	
	return E_事件是否传递::e_事件传递_终止;
}

void f_工作区_切换控制点类型(uint8 类型) {
	C_曲线编辑视口* box = C_曲线编辑视口::g当前操作曲线视口;

	for (auto& id : box->m_拾取索引) {
		auto& point = box->m_动画曲线[id.组]->曲线[id.通道]->point[id.点ID];
		
		point.Select_Type.y = 类型;

		f_an_自动控制点(box->m_动画曲线[id.组]->曲线[id.通道]);
	}
	
}

